//
//  PMGearJoint.m
//  PezMonkey
//
//  Created by Spence DiNicolantonio on 12/24/09.
//  Copyright 2009 Necrosoft. All rights reserved.
//

/**
 * A subclass of PMConstraint for representing gear joints. PMGearJoint are used
 * to maintain a constant angular velocity ratio between two rigid bodies. A 
 * PMGearJoint's phase defines the angular difference between the two rigid bodies 
 * before any rotation is applied. Its ratio defines the angular velocity ratio 
 * of the PMGearJoint's bodyA to bodyB.
 */

#import "PMGearJoint.h"
#import "PMBody.h"


@implementation PMGearJoint

#pragma mark -
#pragma mark Init

/**
 * Returns a PMGearJoint object initialized with a given phase and angular velocity
 * ratio to be maintained between two given rigid bodies.
 */
- (id)initWithBodyA:(PMBody *)aBody bodyB:(PMBody *)otherBody phase:(PMFloat)phase ratio:(PMFloat)ratio {
	if (![super init])
		return nil;
	
	// inverse ratio
	// (because the backend Chipmunk engine has the ratio flipped)
	ratio = 1.0 / ratio;
	
	// allocate and initialize cpConstraint
	constraint = cpGearJointNew(aBody.cpBody, otherBody.cpBody, phase, ratio);
	
	// set body references
	self.bodyA = aBody;
	self.bodyB = otherBody;
	
	// reference this PMConstraint object with cpConstraint's data pointer
	// this is for internal use
	constraint->data = self;
	
	return self;
}


#pragma mark Convenience


/**
 * Creates and returns a PMGearJoint object initialized with a given phase and
 * angular velocity ratio to be maintained between two given rigid bodies.
 */
+ (PMGearJoint *)gearJointWithBodyA:(PMBody *)aBody bodyB:(PMBody *)otherBody phase:(PMFloat)phase ratio:(PMFloat)ratio {
	return [[[PMGearJoint alloc] initWithBodyA:aBody 
										 bodyB:otherBody 
										 phase:phase 
										 ratio:ratio] autorelease];
}


#pragma mark -
#pragma mark Getters

/**
 * Returns the phase angle, in radians, between the receiver's maintained rigid 
 * bodies.
 */
- (PMFloat)phase {
	return cpGearJointGetPhase(constraint);
}

/**
 * Returns the angular velocity ratio maintained by the receiver for its rigid 
 * bodies.
 */
- (PMFloat)ratio {
	// inversed because the backend Chipmunk engine has the ratio flipped
	return (1.0 / cpGearJointGetRatio(constraint));
}


#pragma mark -
#pragma mark Setters

/**
 * Sets the phase angle between the receiver's rigid bodies to a given value, in
 * radians.
 */
- (void)setPhase:(PMFloat)phase {
	cpGearJointSetPhase(constraint, phase);
}

/**
 * Sets the angular velocity ratio maintained by the receiver for its rigid bodies
 * to a given value.
 */
- (void)setRatio:(PMFloat)ratio {
	// inversed because the backend Chipmunk engine has the ratio flipped
	cpGearJointSetRatio(constraint, (1.0 / ratio));
}

@end
